﻿using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace Autoupdate.Common
{
    public class Configuration
    {
        private class Variable
        {
            public string Value;
            public bool Changed;

            public Variable(string value)
            {
                Value = value;
                Changed = false;
            }
        }

        private string mFilePath;
        private Dictionary<string, Variable> mDictionaries;
        private DES mDES;

        public Configuration(DES des)
        {
            mDES = des;
            mDictionaries = new Dictionary<string, Variable>();
        }

        public void Load(string filePath)
        {
            mDictionaries.Clear();

            mFilePath = filePath;
            if (!File.Exists(mFilePath))
                return;

            StreamReader reader = new StreamReader(mFilePath);
            string line, key, value;
            int index;
            while (!reader.EndOfStream)
            {
                line = reader.ReadLine();
                line = Decrypt(line);
                index = line.IndexOf('=');
                if (index == -1)
                    continue;

                key = line.Substring(0, index);
                if (string.IsNullOrEmpty(key))
                    continue;

                if (index >= line.Length - 1)
                    value = string.Empty;
                else
                    value = line.Substring(index + 1);

                mDictionaries.Add(key, new Variable(value));
            }
            reader.Close();
        }

        public void AcceptChanges()
        {
            Save(mFilePath);
        }

        public void Save(string filePath)
        {
            string path = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            StreamWriter writer = new StreamWriter(filePath, false);

            ArrayList keyList = new ArrayList(mDictionaries.Keys);
            keyList.Sort();
            foreach (string key in keyList)
                writer.WriteLine(Encrypt(key + "=" + mDictionaries[key].Value));
               
            writer.Close();
        }

        public void Clear()
        {
            mDictionaries.Clear();
        }

        public bool ContainsKey(string key)
        {
            return mDictionaries.ContainsKey(key);
        }

        public void WriteString(string key, string value, bool allowCreate)
        {
            if (mDictionaries.ContainsKey(key))
            {
                if (mDictionaries[key].Value != value)
                {
                    mDictionaries[key].Value = value;
                    mDictionaries[key].Changed = true;
                }
                return;              
            }
            else
            {
                if (allowCreate)
                    mDictionaries.Add(key, new Variable(value));
            }

            if (!allowCreate)
                Log.WriteError("Configuration.WriteString", "不存在变量 '" + key + "'，写入失败.");
        }

        public string ReadString(string key)
        {
            if (mDictionaries.ContainsKey(key))
                return mDictionaries[key].Value;

            Log.WriteWarning("Configuration.ReadString",
                "不存在变量 '" + key + "'，默认返回空值.");
            return string.Empty;
        }

        public void WriteIntger(string key, int value, bool allowCreate)
        {
            WriteString(key, value.ToString(), allowCreate);
        }

        public int ReadIntger(string key)
        {
            int result = 0;
            string value = ReadString(key);
            if (!int.TryParse(value, out result))
            {
                result = 0;
                Log.WriteError("Configuration.ReadIntger",
                    "变量 '" + key + "' 值为 '" + value + "', 无法转换成int型，默认返回0.");
            }
            return result;
        }

        public void WriteDouble(string key, double value, bool allowCreate)
        {
            WriteString(key, value.ToString(), allowCreate);
        }

        public double ReadDouble(string key)
        {
            double result = 0;
            string value = ReadString(key);
            if (!double.TryParse(value, out result))
            {
                result = 0;
                Log.WriteError("Configuration.ReadDouble",
                    "变量 '" + key + "' 值为 '" + value + "', 无法转换成double型，默认返回0.");
            }
            return result;
        }

        public void WriteBoolean(string key, bool value, bool allowCreate)
        {
            WriteString(key, value.ToString(), allowCreate);
        }

        public bool ReadBoolean(string key)
        {
            bool result = false;
            string value = ReadString(key);
            if (!bool.TryParse(value, out result))
            {
                result = false;
                Log.WriteError("Configuration.ReadBoolean",
                    "变量 '" + key + "' 值为 '" + value + "', 无法转换成bool型，默认返回false.");
            }
            return result;
        }

        public bool IsValueChanged()
        {
            foreach (KeyValuePair<string, Variable> entry in mDictionaries)
            {
                if (entry.Value.Changed)
                    return true;
            }
            return false;
        }

        public bool IsValueChangedForSection(string section)
        {
            foreach (KeyValuePair<string, Variable> entry in mDictionaries)
            {
                if (entry.Key.Contains(section + "."))
                {
                    if (entry.Value.Changed)
                        return true;
                }
            }
            return false;
        }

        public bool IsValueChangedForKey(string key)
        {
            foreach (KeyValuePair<string, Variable> entry in mDictionaries)
            {
                if (entry.Key == key)
                {
                    if (entry.Value.Changed)
                        return true;
                }
            }
            return false;
        }

        public Configuration GetChanges(Configuration config)
        {
            Configuration result = new Configuration(mDES);
            result.mDictionaries.Clear();
            foreach (KeyValuePair<string, Variable> entry in mDictionaries)
                result.mDictionaries.Add(entry.Key, new Variable(entry.Value.Value));
            foreach(KeyValuePair<string, Variable> entry in config.mDictionaries)
            {
                if (result.ContainsKey(entry.Key))
                    result.WriteString(entry.Key, entry.Value.Value, false);
            }
            return result;
        }

        private string Encrypt(string encryptString)
        {
            if (mDES == null)
                return encryptString;
            return mDES.EncryptString(encryptString);
        }

        private string Decrypt(string decryptString)
        {
            if (mDES == null)
                return decryptString;
            return mDES.DecryptString(decryptString);
        }
    }
}
